% 清理变量和关闭所有窗口
clear;
close all;
clc;
% 打开CBMEX
cbmex('open');

% 设置参数
cbmex('trialconfig', 1);


% 初始暂停时间
initial_pause_time = 0.5;
% 额外暂停时间
additional_pause_time = 0.3;


% 跳跃阈值
jump_threshold = 1200;
% 采集的通道号
channels_of_interest = [185, 191, 206, 215, 217, 221, 222, 224];
% 采样率 30khz
sampling_rate = 30000;
% 以手离开startpad为准，前后时间设置
pre_time = 0.45;
post_time = 0.3;
% bin的大小(ms)
spike_bin = 100;
% spike窗口大小（采样点数）
spike_window_samples = pre_time * sampling_rate + post_time * sampling_rate;
% spike窗口的步长(采样点数)
spike_step_samples = spike_bin * sampling_rate / 1000;
% spike矩阵的大小
spike_matrix_size = [length(channels_of_interest), spike_window_samples / spike_step_samples];



% 输出文件名
output_filename = 'spike_matrices.mat';
% 如果文件已经存在，备份并删除
if exist('spike_matrices.mat', 'file') == 2
    currentDate = datestr(now, 'yyyymmdd_HHMMSS');
    backupFilename = ['spike_matrices_', currentDate, '.mat'];
    copyfile('spike_matrices.mat', backupFilename);
    disp(['Backed up existing spike_matrices.mat to ', backupFilename]);
    delete('spike_matrices.mat');
    disp('Deleted existing spike_matrices.mat file.');
end

% 初始化数据缓存
data_buffer = {};
% 所有的spike矩阵
all_spike_matrices = {};
% 所有的时间戳
all_timestamps = [];
startTime = datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss.SSS');

% 开始循环，持续进行数据采集
while true
    % 暂停0.5秒，每隔0.5秒采集一次数据
    pause(initial_pause_time);

    % 获取数据  event_data: 事件数据  time: 时间  cont: 连续数据 并清空机器缓存
    [event_data, time, cont] = cbmex('trialdata', 1);
    
    % 将数据存入缓存
    data_buffer{end+1} = struct('event_data', {event_data}, 'time', time, 'cont', {cont});
    
    % 监测257通道的连续数据 startpad通道
    data = cont{257, 3};
    
    % 计算数据的差分
    diff_data = diff(data);
    % 寻找跳跃点
    jump_indices = find(diff_data > jump_threshold);  
    
    % 对跳跃点进行处理
    for jump_idx = jump_indices'
        % 获取当前数据的长度
        current_length = length(data);

        % 判断跳跃点前后的矩阵窗口
        % 1. start在上一个buffer，end在当前buffer
        if jump_idx - pre_interval_length >= 0 && jump_idx + post_interval_length <= current_length
            spike_start = jump_idx - pre_interval_length;
            spike_end = jump_idx + post_interval_length;
            
            % 计算spike矩阵
            spike_matrix = calculate_spike_matrix(data_buffer{end}, spike_start, spike_end, spike_matrix_size, spike_step_samples, channels_of_interest);
            all_spike_matrices{end+1} = spike_matrix;

            % 记录当前时间
            currentTime = datetime('now');
            elapsedMilliseconds = milliseconds(currentTime - startTime);
            all_timestamps(end+1) = elapsedMilliseconds;

        % 2. start在当前buffer，end在当前buffer
        elseif jump_idx - pre_interval_length >= 0 && jump_idx + post_interval_length <= current_length
            spike_start = jump_idx - pre_interval_length;
            spike_end = jump_idx + post_interval_length;

            % 计算spike矩阵
            spike_matrix = calculate_spike_matrix(data_buffer{end}, spike_start, spike_end, spike_matrix_size, spike_step_samples, channels_of_interest);
            all_spike_matrices{end+1} = spike_matrix;

            % 记录当前时间
            currentTime = datetime('now');
            elapsedMilliseconds = milliseconds(currentTime - startTime);
            all_timestamps(end+1) = elapsedMilliseconds;

        % 3. start在当前buffer，end在下一个buffer
        elseif jump_idx - pre_interval_length >= 0 && jump_idx + post_interval_length > current_length
            % 暂停以获取下一段数据
            pause(additional_pause_time);
            [event_data, time, cont] = cbmex('trialdata', 1);
            data_buffer{end+1} = struct('event_data', {event_data}, 'time', time, 'cont', {cont});
            
            % 重新获取当前数据长度
            current_length = length(data_buffer{end}.cont{257, 3});
            curr_spike_start = jump_idx - pre_interval_length;
            curr_spike_end = current_length;
            next_spike_start = 1;
            next_spike_end = post_interval_length - (current_length - jump_idx);

            % 计算当前和下一段的spike矩阵
            spike_matrix_curr = calculate_spike_matrix(data_buffer{end-1}, curr_spike_start, curr_spike_end, spike_matrix_size, spike_step_samples, channels_of_interest);
            spike_matrix_next = calculate_spike_matrix(data_buffer{end}, next_spike_start, next_spike_end, spike_matrix_size, spike_step_samples, channels_of_interest);
            
            % 合并spike矩阵
            spike_matrix = spike_matrix_curr + spike_matrix_next;
            all_spike_matrices{end+1} = spike_matrix;

            % 记录当前时间
            currentTime = datetime('now');
            elapsedMilliseconds = milliseconds(currentTime - startTime);
            all_timestamps(end+1) = elapsedMilliseconds;

        % 4. start在上一个buffer，end在下一个buffer
        elseif jump_idx - pre_interval_length < 0 && jump_idx + post_interval_length > current_length
            % 暂停以获取下一段数据
            pause(additional_pause_time);
            [event_data, time, cont] = cbmex('trialdata', 1);
            data_buffer{end+1} = struct('event_data', {event_data}, 'time', time, 'cont', {cont});
            
            % 重新获取当前数据长度
            current_length = length(data_buffer{end}.cont{257, 3});
            
            % 获取前一个buffer的数据
            prev_data = data_buffer{end-1}.cont{257, 3};
            prev_length = length(prev_data);
            
            % 计算前一个buffer的spike窗口
            prev_spike_start = prev_length + (jump_idx - pre_interval_length);
            prev_spike_end = prev_length;  % 前一个buffer的结束点
            
            % 当前buffer的spike窗口
            curr_spike_start = 1;
            curr_spike_end = jump_idx + post_interval_length;

            % 计算前一个和当前的spike矩阵
            spike_matrix_prev = calculate_spike_matrix(data_buffer{end-1}, prev_spike_start, prev_spike_end, spike_matrix_size, spike_step_samples, channels_of_interest);
            spike_matrix_curr = calculate_spike_matrix(data_buffer{end}, curr_spike_start, curr_spike_end, spike_matrix_size, spike_step_samples, channels_of_interest);
            
            % 合并spike矩阵
            spike_matrix = spike_matrix_prev + spike_matrix_curr;
            all_spike_matrices{end+1} = spike_matrix;

            % 记录当前时间
            currentTime = datetime('now');
            elapsedMilliseconds = milliseconds(currentTime - startTime);
            all_timestamps(end+1) = elapsedMilliseconds;  % 存储时间戳
        end
    end


% 计算spike矩阵
function spike_matrix = calculate_spike_matrix(buffer, spike_start, spike_end, spike_matrix_size, spike_step_samples, channels_of_interest)
    spike_matrix = zeros(spike_matrix_size);
    for ch = 1:length(channels_of_interest)
        ch_index = channels_of_interest(ch);
        spike_times = buffer.event_data{ch_index, 2};
        for win = 1:spike_matrix_size(2)
            window_start = spike_start + (win-1) * spike_step_samples;
            window_end = window_start + spike_step_samples;
            spike_count = sum(spike_times >= window_start & spike_times <= window_end);
            spike_matrix(ch, win) = spike_count;
        end
    end
end
